package org.ihelpuoo.http;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.ihelpuoo.I;

/**
 * <b>HttpUtil class:</b>
 * <hr color=grey size=1>
 *
 *
 *
 * @author zozoh  created @ 2006
 *
 */
public class HTTP
{
	public static final String	MULTIPART_CONTENT_TYPE	= "multipart/form-data";
	public static final String	DFT_POST_CONTENT_TYPE	= "application/x-www-form-urlencoded";
	public static final String	DFT_BOUNDARY			= "-------[www.ihelpuoo.org]---------8f6589dfw056c";
	public static final String	USER_AGENT				= "iHelpuoo HTTP Sender";
	public static final String	HN_USER_AGENT			= "User-Agent";
	public static final String	HN_CONTENT_TYPE			= "Content-Type";

	public static String retrieveMultipartRequestBoundary(String contentType)
	{
		if (null == contentType)
			return null;
		int pos = contentType.indexOf(";");
		if (pos <= 10)
			return null;
		if (!contentType.substring(0,pos).equalsIgnoreCase(MULTIPART_CONTENT_TYPE))
			return null;
		pos = contentType.indexOf("=",pos);
		if (pos < 0)
			return null;
		return contentType.substring(pos + 1);
	}

	public static String formatMultipartBoundary(String boundary)
	{
		if (null == boundary)
			return null;
		return "--" + boundary;
	}

	public static String formatMultipartName(String name, String filename, String contentType)
	{
		StringBuffer sb = new StringBuffer();
		sb.append("Content-Disposition: form-data; name=\"");
		sb.append(name);
		sb.append("\"");
		if (null != filename)
			sb.append("; filename=\"" + filename + "\"");
		if (null != contentType)
			sb.append("\nContent-Type: " + contentType);
		sb.append(I.NEW_LINE + I.NEW_LINE);
		return sb.toString();
	}

	public static String formatMultipartName(String name)
	{
		return formatMultipartName(name,null,null);
	}

	public static void duplicateHttpHeaders(HttpServletRequest request, URLConnection conn)
	{
		Enumeration<?> en = request.getHeaderNames();
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			conn.setRequestProperty(name,request.getHeader(name));
		}
	}

	public static String dumpInputStream(HttpServletRequest request)
	{
		StringBuffer sb = new StringBuffer();
		sb.append(dumpHeaders(request));
		sb.append(I.NEW_LINE);
		sb.append("<POSTDATA>");
		sb.append(I.NEW_LINE);
		try
		{
			InputStream in = request.getInputStream();
			int c;
			while ((c = in.read()) != -1)
			{
				sb.append((char)c);
			}
			in.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		sb.append(I.NEW_LINE);
		sb.append("</POSTDATA>");
		sb.append(I.NEW_LINE);
		return sb.toString();
	}

	public static String dumpData(HttpServletRequest request)
	{
		Enumeration<?> en = request.getParameterNames();
		StringBuffer sb = new StringBuffer();
		sb.append(dumpHeaders(request));
		sb.append(I.NEW_LINE);
		sb.append("<DATA>");
		sb.append(I.NEW_LINE);
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			sb.append(name + "=" + request.getParameter(name));
			sb.append(I.NEW_LINE);
		}
		sb.append("</DATA>");
		sb.append(I.NEW_LINE);
		return sb.toString();
	}

	static public String dumpHeaders(HttpServletRequest request)
	{
		StringBuffer sb = new StringBuffer();
		Enumeration<?> em = request.getHeaderNames();
		sb.append(I.NEW_LINE);
		sb.append("<HEADERS request=\"" + request.getRequestURL().toString());
		if (null != request.getQueryString())
			sb.append("?" + request.getQueryString());
		sb.append("\"");
		sb.append(I.NEW_LINE + "SESSIONid=\"" + request.getSession().getId() + "\"");
		sb.append(I.NEW_LINE + "ServerName=\"" + request.getServerName() + "\"");
		sb.append(I.NEW_LINE + "ServerPort=\"" + request.getServerPort() + "\"");
		sb.append(I.NEW_LINE + "localAddr=\"" + request.getLocalAddr() + "\"");
		sb.append(I.NEW_LINE + "localName=\"" + request.getLocalName() + "\"");
		sb.append(I.NEW_LINE + "localPort=\"" + request.getLocalPort() + "\"");
		sb.append(I.NEW_LINE + "RemoteAddr=\"" + request.getRemoteAddr() + "\"");
		sb.append(I.NEW_LINE + "RemoteHost=\"" + request.getRemoteHost() + "\"");
		sb.append(I.NEW_LINE + "RemotePort=\"" + request.getRemotePort() + "\"");
		sb.append(I.NEW_LINE + "Encoding=\"" + request.getCharacterEncoding() + "\"");
		sb.append(I.NEW_LINE + "Method=\"" + request.getMethod() + "\"");
		sb.append(">");
		while (em.hasMoreElements())
		{
			String name = (String)em.nextElement();
			sb.append(I.NEW_LINE);
			sb.append("[" + name + "]:");
			sb.append(request.getHeader(name));
		}
		sb.append(I.NEW_LINE);
		sb.append("</HEADERS>");

		return sb.toString();
	}

	public static String dumpHeaders(URLConnection conn)
	{
		StringBuffer sb = new StringBuffer();
		Iterator<?> it = conn.getHeaderFields().keySet().iterator();
		sb.append(I.NEW_LINE);
		sb.append("<HEADERS url=\"" + conn.getURL().toString() + "\">");
		while (it.hasNext())
		{
			String name = (String)it.next();
			sb.append(I.NEW_LINE);
			sb.append("[" + name + "]:");
			sb.append(conn.getHeaderField(name));
		}
		sb.append(I.NEW_LINE);
		sb.append("</HEADERS>");
		return sb.toString();
	}

	public static String sendSimpleGetRequest(String url, String encoding)
			throws FailToConnectException
	{
		StringBuffer sb = new StringBuffer();
		try
		{
			URL oUrl = new URL(url);
			URLConnection conn = oUrl.openConnection();
			BufferedReader br = new BufferedReader(null == encoding ? new InputStreamReader(conn
					.getInputStream()) : new InputStreamReader(conn.getInputStream(),encoding));
			String line;
			while ((line = br.readLine()) != null)
			{
				sb.append(line).append(I.NEW_LINE);
			}
			br.close();
			br = null;
		}
		catch (MalformedURLException e1)
		{
			throw new FailToConnectException("MalformedURL: " + url + "\t" + e1.getMessage(),e1);
		}
		catch (UnknownHostException e2)
		{
			throw new FailToConnectException("UnknownHost: " + url + "\t" + e2.getMessage(),e2);
		}
		catch (NoRouteToHostException e3)
		{
			throw new FailToConnectException("NoRouteToHost: " + url + "\t" + e3.getMessage(),e3);
		}
		catch (IOException ioe)
		{
			throw new FailToConnectException(ioe.getMessage(),ioe);
		}
		return sb.toString();
	}

	public static String sendSimplePostRequest(String url, Map<String, Object> data, String inenc,
			String reenc) throws FailToConnectException
	{
		StringBuffer sb = new StringBuffer();
		try
		{
			URL oUrl = new URL(url);
			URLConnection conn = oUrl.openConnection();
			if (null != data && data.size() > 0)
			{
				conn.setDoOutput(true);
				Writer w = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
				Iterator<String> it = data.keySet().iterator();
				String key = it.next();
				Object v = data.get(key);
				w.write(URLEncoder.encode(key,inenc));
				w.write('=');
				if (null != v)
					w.write(URLEncoder.encode(data.get(key).toString(),inenc));
				while (it.hasNext())
				{
					key = it.next();
					w.write('&');
					w.write(URLEncoder.encode(key,inenc));
					w.write('=');
					v = data.get(key);
					if (null != v)
						w.write(URLEncoder.encode(data.get(key).toString(),inenc));
				}
				w.flush();
				w.close();
				w = null;
			}
			// Get the response
			BufferedReader br = new BufferedReader(null == reenc ? new InputStreamReader(conn
					.getInputStream()) : new InputStreamReader(conn.getInputStream(),reenc));
			String line;
			while ((line = br.readLine()) != null)
			{
				sb.append(line).append(I.NEW_LINE);
			}
			br.close();
			br = null;
		}
		catch (MalformedURLException e1)
		{
			throw new FailToConnectException("MalformedURL: " + url + "\t" + e1.getMessage(),e1);
		}
		catch (UnknownHostException e2)
		{
			throw new FailToConnectException("UnknownHost: " + url + "\t" + e2.getMessage(),e2);
		}
		catch (NoRouteToHostException e3)
		{
			throw new FailToConnectException("NoRouteToHost: " + url + "\t" + e3.getMessage(),e3);
		}
		catch (IOException ioe)
		{
			throw new FailToConnectException(ioe.getMessage(),ioe);
		}
		return sb.toString();
	}

	public static String dumpSessionAttributes(HttpSession session)
	{
		StringBuffer sb = new StringBuffer();
		Enumeration<?> en = session.getAttributeNames();
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			sb.append("[" + name + "]: " + session.getAttribute(name) + "\n");
		}
		return sb.toString();
	}

	public static String dumpContextAttributes(ServletContext context)
	{
		StringBuffer sb = new StringBuffer();
		Enumeration<?> en = context.getAttributeNames();
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			sb.append("[" + name + "]: " + context.getAttribute(name) + "\n");
		}
		return sb.toString();
	}

	public static String dumpRequestAttributes(ServletRequest request)
	{
		StringBuffer sb = new StringBuffer();
		Enumeration<?> en = request.getAttributeNames();
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			sb.append("[" + name + "]: " + request.getAttribute(name) + "\n");
		}
		return sb.toString();
	}

	public static String dumpRequestParams(ServletRequest request)
	{
		StringBuffer sb = new StringBuffer();
		Enumeration en = request.getParameterNames();
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			sb.append("[" + name + "]: " + request.getParameter(name) + "\n");
		}
		return sb.toString();
	}

	public static String getUserAgent(HttpServletRequest request)
	{
		return request.getHeader("user-agent");
	}

	public static String dumpBrief(HttpServletRequest request)
	{
		StringBuffer sb = new StringBuffer();
		Enumeration en = request.getParameterNames();
		while (en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			sb.append(name);
			String v = request.getParameter(name);
			if (v != null)
			{
				sb.append("=");
				sb.append(v);
			}
			if (en.hasMoreElements())
				sb.append("&");
		}
		return String.format("%5s:%15s[%5s]%s",new Object[]{
				request.getLocale().toString(),
				request.getRemoteAddr(),
				((HttpServletRequest)request).getMethod(),
				((HttpServletRequest)request).getRequestURL().toString()
						+ (sb.length() > 0 ? "?" + sb.toString() : "")});
	}
}